using System;
using System.Collections.Generic;
using System.Text;

namespace RStarTree
{
    public  class relation
    {
        public char T;      // Topological relation
        public double D;    // distance relation
        public double A;    // Directional relation

        /**Initializes relations between two given rectangles r1,r2
        */

        public relation(rectangle r1, rectangle r2)
        {
            this.D = distance(r1, r2);
            this.A = angle(r1, r2);
            this.T = topological(r1, r2);
        }

        /** Creates a new empty relation object.
        */

        public relation()
        {
            this.D = -1;
            this.A = -1;
            this.T = ' ';
        }

        /** Calculates the distance between the centroids two rectangles.
        */

        public static double distance(rectangle r1, rectangle r2)
        {
            double x1, y1, x2, y2;
            double d;
            x1 = (r1.LX + r1.UX) / 2;
            y1 = (r1.LY + r1.UY) / 2;
            x2 = (r2.LX + r2.UX) / 2;
            y2 = (r2.LY + r2.UY) / 2;
            d = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
            return d;
        }

        /** Calculates the angle between the centroids of two rectangles.
        */

        public static double angle(rectangle r1, rectangle r2)
        {
            double x1, y1, x2, y2;
            double x, y;
            double u, d;
            x1 = (r1.LX + r1.UX) / 2;
            y1 = (r1.LY + r1.UY) / 2;
            x2 = (r2.LX + r2.UX) / 2;
            y2 = (r2.LY + r2.UY) / 2;
            x = x1 - x2;
            y = y1 - y2;
            u = Math.Atan2(x, y);
            u -= Math.PI / 2;
            if (u < -Math.PI) u += 2 * Math.PI;
            if ((x >= 0) && (y >= 0))
            {
                d = u * 180 / Math.PI;
            }
            if ((x >= 0) && (y >= 0))
            {
                d = u;
            }

            if (u >= 0)
            {
                d = u * 180 / Math.PI;
            }
            else
            {
                d = 360 + u * 180 / Math.PI;
            }
            return d;
        }

        /** Calculates the topological relation between two rectangles.
        */

        public static char topological(rectangle r1, rectangle r2)
        {
            char c;
            if ((r1.LX == r2.LX) &&
                (r1.LY == r2.LY) &&
                (r1.UX == r2.UX) &&
                (r1.UY == r2.UY)) return 'E';  // EQUAL
            if ((r1.LX > r2.LX) &&
                (r1.LY > r2.LY) &&
                (r1.UX < r2.UX) &&
                (r1.UY < r2.UY)) return 'I';   // INSIDE
            if ((r1.LX < r2.LX) &&
                (r1.LY < r2.LY) &&
                (r1.UX > r2.UX) &&
                (r1.UY > r2.UY)) return 'C';   // CONTAINS
            if ((r1.LX >= r2.LX) &&
                (r1.LY >= r2.LY) &&
                (r1.UX <= r2.UX) &&
                (r1.UY <= r2.UY)) return 'B';  // COVER BY
            if ((r1.LX <= r2.LX) &&
                (r1.LY <= r2.LY) &&
                (r1.UX >= r2.UX) &&
                (r1.UY >= r2.UY)) return 'V';  // COVERS
            if ((r1.LX < r2.UX) &&
                (r1.LY < r2.UY) &&
                (r1.UX > r2.LX) &&
                (r1.UY > r2.LY)) return 'O';   // OVERLAP
            if ((r1.LX <= r2.UX) &&
                (r1.LY <= r2.UY) &&
                (r1.UX >= r2.LX) &&
                (r1.UY >= r2.LY)) return 'M';  // MEET
            return 'D';                         // DISJOIN
        }

        /** Calculates the converse of a given topological relation.
        */

        public static char converseTopological(char t)
        {
            switch (t)
            {
                case 'D':
                    return 'D';
                case 'O':
                    return 'O';
                case 'M':
                    return 'M';
                case 'E':
                    return 'E';
                case 'V':
                    return 'B';
                case 'B':
                    return 'V';
                case 'C':
                    return 'I';
                case 'I':
                    return 'C';
                default:
                    return ' ';
            }
        }
    }
}
